#include "ipmacscan.h"
#include "network.h"
#include "router.h"
#include "menu.h"

#include <net/if.h>
#include <pthread.h>
#include <signal.h>
#include <linux/if_packet.h>

// 初始化功能请求,-1:表示没有任何请求
int cliAcpFuncFlag = -1;

// 读取文件获取网卡名称
int activeMacRead(char* macFilePath, char* macName)
{
    if(macFilePath == NULL){
        printf("没有输入网卡文件路径");
        DEBUGERROR;
        return 0;
    }

    char macNameLine[paraSize/2];
    memset(macNameLine, '\0', sizeof(macNameLine));

    // 读取网卡名称
    FILE* fd = fopen(macFilePath, "r");
    if (fd == NULL) {
        printf("无法打开文件\n");
        DEBUGERROR;
        return -1;
    }

    // 逐行读取文件内容
    int i = 0;
    while (fgets(macNameLine, paraSize/2, fd) != NULL) {
        //printf("%s", macNameLine);
        strcpy(&macName[i++], macNameLine);
    }

    return 1;
}


// 解析不同网段数据流中的数据
// buf只是数据流中存在Ip和Data的缓存数据
analyIpData* analyDiffNetIpData(uc8 *buf)
{
    if(buf == NULL && strlen(buf)==0){
        printf("数据流没有信息");
        DEBUGERROR;
        return NULL;
    }

    analyIpData* bufIpData = (analyIpData*)malloc(sizeof(analyIpData));
    uc8* token;
    token = strtok(buf, "/D/");
    bufIpData->diffDstIp = (uc8*)malloc(sizeof(uc8)*strlen(token));
    strcpy(bufIpData->diffDstIp, token); // 复制不同目的网段的IP

    token = strtok(NULL, "/D/");
    bufIpData->diffDstData = (uc8*)malloc(sizeof(uc8)*(strlen(token)+1));
    strcpy(bufIpData->diffDstData, token); // 复制给不同目的网段的数据

    bufIpData->diffDstData[strlen(bufIpData->diffDstData)] = '\0';

    // 判断是否是解析成功
    if(bufIpData->diffDstIp != NULL && bufIpData->diffDstData != NULL){
        cliAcpFuncFlag = 1; // 不同网段通信协议请求
        return bufIpData;
    }

    return NULL;
}

// 解析功能选择数据流中的数据
// buf只是数据流中存在功能号和的缓存数据
bufAptData* analyFuncSelectBuf(uc8 *buf)
{
    if (buf == NULL && strlen(buf) == 0) {
        printf("数据流没有信息");
        DEBUGERROR;
        return NULL;
    }


    bufAptData* bufFuncData = (bufAptData*)malloc(sizeof(bufAptData));
    uc8* token;

    token = strtok(buf, "/F/"); // 解析出功能号
    bufFuncData->FuncName = -1;  
    bufFuncData->FuncName = atoi(&token[0]); // 保存选择功能号
    if(!(bufFuncData->FuncName >= 0 && bufFuncData->FuncName <= 8)){
        bufFuncData->FuncName = -1; // 防止不是功能菜单的功能
    }

#if 0
    if (strlen(&token[1]) != 0)
    {
        DEBUG;
        token = strtok(NULL, "/F/");
        bufFuncData->FuncAptData = (uc8*)malloc(sizeof(uc8) * (strlen(token) + 1));
        strcpy(bufFuncData->FuncAptData, token); // 复制给不同目的网段的数据
        bufFuncData->FuncAptData[strlen(bufFuncData->FuncAptData)] = '\0';
        printf("funcData:%s\n", bufFuncData->FuncAptData);
    }
    else {
        strcpy(bufFuncData->FuncAptData, token); // 复制给不同目的网段的数据
    }
#else
    token = strtok(NULL, "/F/");
    bufFuncData->FuncAptData = (uc8*)malloc(sizeof(uc8) * (strlen(token) + 1));
    strcpy(bufFuncData->FuncAptData, token); // 复制给不同目的网段的数据
    bufFuncData->FuncAptData[strlen(bufFuncData->FuncAptData)] = '\0';
    printf("funcData:%s\n", bufFuncData->FuncAptData);
#endif 

    // 判断是否是解析成功
    if(bufFuncData->FuncName != -1 && bufFuncData->FuncAptData != NULL){
        //cliAcpFuncFlag = 2; // 功能选择数据协议请求
        return bufFuncData;
    }

    return NULL;
}

// udp报头解析
// 不同网段通信协议:(170.254.210.100/D/asdasd/)
// 功能选择协议:(170.254.210.100/F/asdasd/)
// 只返回不同网通信时的结构体,功能选择不进行返回
analyIpData* udpDecomposeMessages(uc8* buf, uc8* strIp, us16 ipHeadLen, ipMac* allIpMacIfo)
{
    uc8* bufUdp = buf + 14 + ipHeadLen; // 跳过mac头和ip
    us16 srcport = ntohs(*(us16*)(bufUdp+0));
    us16 dstport = ntohs(*(us16*)(bufUdp+2));
    //printf("srcport:%hu, dstport:%hu\n", srcport, dstport);
    char* bufData = (char*)(bufUdp+8);

    // 判断是否是同一网段
    uc8* retDiff = strstr(bufData, "/D/");
    // 功能协议判断
    uc8* retFunc = strstr(bufData, "/F/");

    // 如果不存在/D/和/F/,在同一个网段中,不进行处理
    if(retDiff == NULL && retFunc == NULL){
#if 1
        if(strlen(bufData) < 254){
            printf("数据:%s\n", bufData);
        }
#endif  
        cliAcpFuncFlag = 0; // 同一网段通信请求
        return NULL;
    }else if(retDiff != NULL && retFunc == NULL){ // 不同网段通信协议处理
        printf("不同网段数据通信\n");
        return analyDiffNetIpData(bufData); 
    }else if(retDiff == NULL && retFunc != NULL){ // 功能选择协议处理
        printf("功能能选项数据处理\n"); 
        cliAcpFuncFlag = 2;
    }

    return NULL;
}

// 应用层转发数据
int appLayerForwardData(analyIpData* analyBufIpData)
{   
    // UDP套接字初始化
    int port = 8000;
    int sfd = socketInit(analyBufIpData->diffDstIp, &port, UDP_FLAG, CLI_FLAG);
    // UDP客户端,用于发送数据
    int ret = socketClient(&sfd, analyBufIpData->diffDstData, UDP_FLAG);
    if(ret < 0){
        printf("数据发送失败\n");
    }
    close(sfd);
    return ret;
}

// 回复客户端的消息
int replyMessage(bufAptData* funcReplyData, uc8* buf)
{   
    // UDP套接字初始化
    int port = 8000;
    int sfd = socketInit(funcReplyData->srcFuncIp, &port, UDP_FLAG, CLI_FLAG);
    // UDP客户端,用于发送数据
    int ret = socketClient(&sfd, buf, UDP_FLAG);
    if(ret < 0){
        printf("数据发送失败\n");
    }
    close(sfd);
    return ret;
}

// 线程信号处理函数
void sig_handler(int signum) {
    if (signum == SIGTERM) {
        //printf("退出当前线程\n");
        pthread_exit(NULL);
    }
}

// 解析出ip和mac地址
// 需要将过滤链表传过滤,进行过滤处理以及其他处理
void* rawSocket(void* data)
{
    ipMacIfo* ipMacData = (ipMacIfo*)data;
    int filterFlag = 0; // 假设不需要过滤 

    int sockFd = ipMacData->sockFd; // 将sockFd保存到临时变量中
    // printf("进行IP协议处理\n");
    // 获取扫描的IP和MAC地址
    ipMac* allIpMacIfo = ipMacData->ipMacHead;
    ipMac* ipMacFilterIfo = ipMacData->ipMacFilterHead;

    while(1){
        //printf("当前在线程2\n");
        // 用于处理线程信号
        signal(SIGTERM, sig_handler);

        // 接受数据
        uc8 buf[2048];
        memset(buf, 0, sizeof(buf));
        int ret = recvfrom(sockFd, buf, sizeof(buf), 0, NULL, NULL);
        if(ret < 0){
            perror("recvfrom");
            DEBUGERROR;
            return NULL;
        }else if (ret == 0) {
             // 连接已关闭，处理关闭情况
             printf("连接关闭\n");
             return NULL;
        } 
        buf[strlen(buf)-1] = '\0';

        uc8 srcMac[18] = "";
        uc8 dstMac[18] = "";
        us16 macType = 0;
        // 解析目的MAC
        sprintf(dstMac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[0],
        buf[1], buf[2], buf[3], buf[4], buf[5]);
        // 解析源MAC
        sprintf(srcMac, "%02x:%02x:%02x:%02x:%02x:%02x", buf[6],
        buf[7], buf[8], buf[9], buf[10], buf[11]);

        macType = ntohs(*(us16*)(buf+12));

        if(macType == 0x0800){
            //printf("ip协议\n");
            uc8* bufIp = buf + 14; // 跳过mac头部
            // 取IP首部长度
            uc8 ipHeadLen = (bufIp[0]&0x0f)*4;
            uc8 srcIp[16] = "";
            uc8 dstIp[16] = "";

            sprintf(srcIp, "%d.%d.%d.%d", bufIp[12], 
            bufIp[13], bufIp[14], bufIp[15]);
            sprintf(dstIp, "%d.%d.%d.%d", bufIp[12+4], 
            bufIp[13+4], bufIp[14+4], bufIp[15+4]);

            // 通过IP地址判断是否进行过滤
            filterFlag = queryIpMacExist(ipMacFilterIfo, srcIp, NULL);
            // IP查找,目标和源IP都存在才进行处理
            int srcIpRecSign = queryIpMacExist(allIpMacIfo, srcIp, NULL);
            int dstIpRecSign = queryIpMacExist(allIpMacIfo, dstIp, NULL);
            int cardIpRecSign = ipMacRouterCmp(dstIp, NULL);

            //if(cardIpRecSign == 0)
              //  printf("dstIp:%s\n", dstIp);
            
            // 判断传输协议,以及进行处理方式
            if((filterFlag == 0)){ // 0时表示过滤表中没有
               if(bufIp[9] == 6){
                }else if( bufIp[9] == 17){
                    if(srcIpRecSign & dstIpRecSign || cardIpRecSign == 0){ // 当源地址和目标地址存在时,才会进行处理
                        analyIpData* analyBufIpData = 
                        udpDecomposeMessages(buf, srcIp, ipHeadLen, allIpMacIfo);
#if 0          
                        printf("srcIp: %s\n", srcIp);
                        printf("dstIp: %s\n", dstIp);
#endif
                        if(analyBufIpData != NULL && cliAcpFuncFlag == 1){
                            int srcIpSign = queryIpMacExist(allIpMacIfo, analyBufIpData->diffDstIp, NULL);
                            int dstIpSign = queryIpMacExist(ipMacFilterIfo, analyBufIpData->diffDstIp, NULL);
                            if(srcIpSign == 0 && cardIpRecSign != 0){
                                printf("不存在该地址\n");
                            }else if(dstIpSign == 1){
                                printf("此为钓鱼网址\n");
                            }else if(srcIpSign && (!dstIpSign)){ // 进行数据转发
                                appLayerForwardData(analyBufIpData);
                                cliAcpFuncFlag = -1; // 初始化为-1, 防止误用
                            }
                        }else if(analyBufIpData == NULL && cliAcpFuncFlag == 2){
                            uc8* bufData = buf + 22 + ipHeadLen; // 获取数据流的数据
                            bufAptData* funcSelectData = analyFuncSelectBuf(bufData);
                            if(funcSelectData != NULL){
                                funcSelectData->srcFuncIp = srcIp; // 保存
                                man_function(funcSelectData, ipMacData);
                            }
                            cliAcpFuncFlag = -1; // 初始化为-1, 防止误用
                        }
                    }
                } 
            }
            else{
                printf("此为钓鱼网站\n");
            }
           
        }else if(macType == 0x0806){
            //printf("ARP协议\n");
        }
    }

   return NULL;
}

// 处理ARP应答后,IP和MAC的解析
// ARP扫描时,不会扫描的自身的IP,导致没有存储到IP和MAC地址中
void* arpIpMacHandle(void* data)
{
    ipMacIfo* ipMacData = (ipMacIfo*)data;
    int sfd= ipMacData->sockFd;
    ipMac* ipMacHead = ipMacData->ipMacHead;

    while(1){
        //收数据
        uc8 buf[2048]="";

        int len = recvfrom(sfd, buf, sizeof(buf), 0, NULL, NULL);
        if(len <= 0){
            break;
        }

        us16 mactype = ntohs(*(us16*)(buf+12));
        us16 op = ntohs(*(us16*)(buf+20));

        if(!arpExitFlag){
            // printf("退出ARP扫描线程\n");
            break;
        }

        if((mactype == 0x0806)&&(op == 2))
        {
            uc8 srcip[16]="";//应答主机IP
            inet_ntop(AF_INET,buf+28,srcip,16);
            uc8 srcmac[18]="";//应答主机MAC地址

            sprintf(srcmac,"%02x:%02x:%02x:%02x:%02x:%02x",
                    buf[6],buf[7],buf[8],buf[9],buf[10],buf[11]);

            ipMacSize *dataSize;
            dataSize = (ipMacSize*)malloc(sizeof(ipMacSize));
            memset(dataSize, 0, sizeof(ipMacSize));
            dataSize->ipSize = sizeof(srcip);
            dataSize->macSize = sizeof(srcmac);

            if(queryIpMacExist(ipMacHead, srcip, NULL) == 0){
                if(insertIpMacData(ipMacHead, srcip, srcmac, dataSize) != 1){
                    DEBUGERROR;
                    perror("insertIpMacData()");
                    exit(0);
                }
            }
        }
    }

    return NULL;
}

//ARP请求/应答函数
int arpReply(ipMacIfo** ipMacData)
{
    //获取原始套接字
    int sfd = (*ipMacData)->sockFd;
    ipMac *ipMacHead = (*ipMacData)->ipMacHead;
    // 获取网卡名称,并根据网卡的信息进行ARP扫描
    int j = 0;
    int i = 1;
    for(j = 0; j < (*ipMacData)->ensCnt; ++j){
        char ens[20] = ""; 
        strcpy(ens, (*ipMacData)->netCard[j]);
        //printf("开始ARP扫描\n");
        // 获取ubantu下源IP和MAC
        uc8* srcIpBuf = (*ipMacData)->sourceIp; // 源ip地址 
        uc8* srcMacBuf = (*ipMacData)->sourceMac; // 源mac地址 

        // 创建线程扫描局域网中所有IP和MAC
        pthread_t ptdArp;
        // 创建线程扫描局域网中所有IP和MAC
        pthread_create(&ptdArp, 0, arpIpMacHandle, (*ipMacData));
        // 猜测使用线程分离原因,需要每一个IP都要一个线程进行解析
        pthread_detach(ptdArp);

        //组包应答,获取局域网中活跃的IP
        uc8* ip_buf = srcIpBuf;
        int ipStartAddress = ipAddress(j); // ip访问起始地址获取
        int macStartAddress = macAddress(j); // ip访问起始地址获取

        for(i = 1; i < 255; ++i){ // 循环获取局域网内所有IP和MAC
            ip_buf[ipStartAddress+3] = i;
            uc8 buf[]={
                0xff,0xff,0xff,0xff,0xff,0xff,  //  目的MAC地址
                // yangu:00:0c:29:b8:40:4b
                srcMacBuf[macStartAddress],srcMacBuf[macStartAddress+1],srcMacBuf[macStartAddress+2],
                srcMacBuf[macStartAddress+3],srcMacBuf[macStartAddress+4],srcMacBuf[macStartAddress+5], // 源MAC(ubuntu)
                0x08,0x06,  //  帧类型
                0x00,0x01,  //  硬件类型
                0x08,0x00,  //  协议类型
                6,  //  硬件地址长度
                4,  //  协议地址长度
                0,1,    //  ARP请求
                srcMacBuf[macStartAddress],srcMacBuf[macStartAddress+1],srcMacBuf[macStartAddress+2],
                srcMacBuf[macStartAddress+3],srcMacBuf[macStartAddress+4],srcMacBuf[macStartAddress+5], // 源MAC(ubuntu)
                srcIpBuf[ipStartAddress],srcIpBuf[ipStartAddress+1],
                srcIpBuf[ipStartAddress+2],srcIpBuf[ipStartAddress+3],
                0x00,0x00,0x00,0x00,0x00,0x00,  //  目的MAC地址
                // 10,7,189,59
                ip_buf[ipStartAddress],ip_buf[ipStartAddress+1],
                ip_buf[ipStartAddress+2],i
            };

            //绑定网络端口
            struct sockaddr_ll sll;     
            memset(&sll, 0, sizeof(sll));
            sll.sll_ifindex = if_nametoindex(ens);

            if(sll.sll_ifindex == 0){
                perror("if_nametoindex");
                close(sfd);
                return -1;
            }
            //发送ARP请求
            sendto(sfd, buf, sizeof(buf), 0, (SA*)&sll, sizeof(sll)); 
        }
    }

    // 判断ARP扫描线程是否退出
    if(i >= 254 && j >= (*ipMacData)->ensCnt){
        arpExitFlag = false;
    }
       
    return 1;
}





